home *** CD-ROM | disk | FTP | other *** search
- Date: Sun, 25 Aug 85 23:02:37 edt
- From: jcm@ornl-msr.ARPA (James A. Mullens)
- To: info-ibmpc@usc-isib.ARPA
- Subject: PRINT.COM 3.1 Internals
-
-
- I offer the following description of the internals of PRINT.COM for
- DOS 3.1 as a guide for those wishing to implement background tasks
- under DOS 3.1. This is the non-networked version of PRINT.COM.
-
- This information is a good starting point for serious hackers,
- determined to implement their own background task or collapse over the
- keyboard trying. I won't bore you with all of the reasons you should
- not write such a background task -- just let me say that if you do, be
- prepared to assume full responsibility for your actions and the actions
- of your program!
-
- I am giving this to the public domain mostly because I think some people
- might have some fun trying to use this stuff, and because I hope some
- public domain programs will turn up. This little project required
- the interpretation of 47 pages of uncommented assembly language, which
- relocates itself, uses 3 different CSs, and has innumerable subroutines.
- I doubt that I am the first to do this, but I appear to be the first to
- offer my findings to the net.
-
- The description is only partially complete. I tried to concentrate on
- the parts of PRINT.COM related to the problem of calling DOS functions.
- I cannot say that all you need to know is here because I have not
- tried to write a background program that calls DOS. Even if I had an
- (apparently) working background program, I would hesitate to say that
- it didn't have a bug which would rear its ugly head in the future.
-
- I look forward to exchanging notes with anyone else who takes an
- interest! If you do something in the near future, please send a
- message to me directly (in addition to the network) so that I won't
- be attempting to do something you have already done.
-
-
- DESCRIPTION OF DOS 3.1 PRINT.COM INTERNALS
- James A Mullens / jcm@ornl-msr
- August 1985
-
- First Stage Setup
-
- Compute stack address and entry point for second stage of setup.
- Adjust some values pointed to by a table.
- Relocate most of program, moving down 310 bytes.
- JMP FAR to second stage setup, changing CS:IP.
-
- Second Stage Setup
-
- Check DOS version.
- Free Allocated Memory.
- Save pointers to old INTs 28,2F,13,15,17,14,05, and 1C if
- spooler is not installed already.
- If spooler already installed, but OK to reinstall, do so.
- If not OK to reinstall do something (?) which may result
- in task terminate with result code FF.
- Do INT 37 (DOS internal). Reason for doing?
- Scan command line, possibly adding filename passed to spool
- queue. Operations done here may result in closing of
- file handles 0 - 5 and terminate with result code 0.
- Many operations involving byte memory comparisons and
- subroutine calls...
- Get current disk (DOS func 19). (Label L15FF)
- Get current directory (DOS func 47). (Label L1627)
- Get extended error (DOS func 59). (Label L1730)
- Skip remainder of setup if PRINT is already installed.
- Simply submit new file for spooling.
- Ask for name of device to spool to.
-
- Third Stage Setup - installation of memory resident portion.
-
- Find DOS driver for output device.
- This involves DOS func 52, perhaps to find a pointer to the
- device driver list. Reject any block-structured device
- as an output device.
- INT redirection. Save and reset vectors for INTs 28,13,15,
- 17,14, and 05.
- DOS function 34 to get location of the INDOS flag in ES:BX.
- The INDOS flag is not used in the same way as DOS v2.0
- used it.
- Save old INT 1C handler address.
- Get print spooler installed state. If not installed, install
- new INT 1C handler. If spooler already installed,
- test a flag to determine if should not install new
- INT 1C handler.
- Install new INT 1C handler if necessary.
- Print 'resident part of print installed'.
- Far jump to address stored at CS:[0E73H]. I assume this exits.
-
- Timer (INT 1C) actions
-
- (Hex numbers refer to memory locations).
-
- Do an INT 2A and exit if carry set. This is an undocumented
- INT, but interesting. It seems one is obliged to do
- INT 2A before exiting interrupt if this call was successful.
- This may be a simple guard against re-entering this 1C
- handler.
- Increment 2D7 and 2D8. Used in the print action routine.
- If 2D9 is not 0, decrement it and
- exit after calling INT 2A. (2D9 is a tick countdown 'timer'.
- Print actions are done only when it counts down to 0).
- If 2CC is not 0, exit without doing INT 2A, else read 8259
- interrupt status register. Exit after doing INT 2A if
- any interrupts except the timer are active.
- 2CC is also increment/decremented in the INT 28 handler and
- the ROM BIOS INT 13 handler (note bene).
- Check INDOS flag byte and the byte _before_ it. If any bits
- are set, exit after doing INT 2A.
- Increment 2CC (flag that print actions are being done).
- Zero 2D7 and 2D8.
- Enable interrupts.
- Test byte flag 2D5. If any bits set, do not send EOI to
- 8259. This flag appears to be used to communicate with the
- INT 2F handler. Possibly the INT 2F handler can invoke
- this INT 1C handler, in which case hardware interrupt stuff
- should not be done.
- Do any print actions needed (including write, read, open a
- new spool file, print error messages, etc.).
- Disable interrupts.
- Move 2DA to 2D9. (Reset countdown timer).
- Decrement 2CC. (Flag that print actions are over).
- Do INT 2A.
- If 2D5 has no bits set call old INT 1C handler, otherwise
- exit via IRET.
-
- INT 2F (new handler inserted by PRINT)
-
- This handler is documented in the DOS manual.
-
- INT 28 Actions (new handler inserted by PRINT)
-
- INT 28 is undocumented, 'used internally by DOS'. This INT
- will also cause print actions to do done under certain
- conditions. It is believed that INT 28 calls are made by the
- DOS 'get from keyboard' routines whenever it is safe to do
- file i/o. (See the net's archive file documenting DOS
- functions and interrupts.) Notice that no attempt is made
- to examine the 'INDOS' flag.
-
- Call INT 2A. If carry set, exit immediately.
- If 2CC is not 0, exit after calling INT 2A.
- Increment 2CC and 2D6.
- Disable INTs.
- Do Print actions (identical to INT 1C handler actions).
- Zero 2D6, move 2DA to 2D9 (byte), decrement 2CC.
- Do INT 2A and continue with old INT 28 handler.
-
- Print Actions called by INT 1C and INT 28 handlers
-
- This is a very elaborate piece of code. A queue of files
- to print is maintained. Files are opened and closed.
- Errors are handled. Etc, etc. I assume most people will
- not be interested in how the file spooling is done.
-
- The extended file management group of DOS functions are
- used for file i/o.
-
- In the print action routine, DOS functions 50 and 51
- are used whenever file i/o is done. Some condition is indicated
- by a flag of 0 or 1. The print action routine and INT 2F
- handler explicitly switch to state 0 before terminating.
- This is done by moving a word to BX and calling DOS function
- 50. Whenever file i/o is to take place, the state is switched
- to 1. This is done by calling DOS
- function 51, saving a result in BX to the word used above,
- moving a new word into BX, and calling DOS function 50.
-
- I have 2 clues as to what DOS functions 50 and 51 do. One
- source says DTA stuff for DOS 2.x, another source says
- PSP stuff for DOS 3.x. (The net's archive file documenting
- DOS functions says with assurance that 50 sets a PSP address
- and 51 gets the current PSP address. This seems to be so.)
- If these are PSP actions, then state 1 has the PSP set to its
- original value (on PRINT.COM entry), and this is the state
- set when doing file i/o. I do not know why it is changed
- when print actions are over.
-
- DOS function 5D is called just prior to exiting the print
- actions routine.
-
- See the discussion of the INT 15 handler below for a special
- case of control-break handling when doing DOS function calls.
-
- Special character handling:
- Backspace erases the previous character.
- Non-printing control characters are filtered.
- Tabs are expanded and all of the spaces sent
- immediately to the output device -- the code seems to have the
- philosophy that all output resulting from the current input
- character must be done in the current call of the INT 1C
- handler.
-
- Output is done by calling device driver 'strategy' and
- 'interrupt' routines. (A device 'interrupt' routine has
- nothing to do with machine interrupts -- it only performs
- the actions indicated by the strategy call.)
- The device state is checked prior to write commands to see if
- the device is busy or has an error. PRINT will attempt to
- get a 'ready' state 20,000 times before giving up.
-
- New ROM BIOS interrupt handlers.
-
- Disk handler (INT 13)
- Increment 2CC on entry, decrement 2CC on exit.
- This flag is checked and used by INT 1C handler and
- INT 28 handler also.
- Cassette and other device handler (INT 15)
- The calls expected by the new handler do not conform
- to IBM PC ROM BIOS cassette tape handler.
- I notice that the AT supports a variety of device
- calls through this vector, but I haven't seen a
- documented call for the function this new INT 15
- handler intercepts (AH = 20).
-
- The new handler would pass all 'old cassette' calls
- to ROM BIOS. Any call with AH = 20 would be
- intercepted. If AL > 1, go to the old handler.
- (On the old cassette handler, AH > 1 meant do a
- read/write). If AL = 1, zero flag CBB and return.
- (On the old cassette handler, AH = 1 meant turn the
- motor off). If AL > 1, increment CBB and move the
- passed ES:BX to CBC, and return.
- When the Print Action routine does file i/o, it goes
- to great pains to disable control-break recognition
- whenever flag CBB is set. When CBB is set, the file
- i/o routine increments the byte pointed to by CBC,
- then does the i/o, and then decrements the byte.
- Printer handler (INT 17)
- Reject all calls for printer unit which is the output
- device. (Use flag 2CC to determine if call is from
- PRINT code.
- Serial Port handler (INT 14)
- Similar to printer handler.
- Print Screen handler (INT 05)
- Reject call unless not spooling to printer 0.
-
- SUMMARY
-
- Run the background task off timer (1C) interrupts.
-
- You may be required to implement an INT 28 handler if
- it is necessary to perform file operations while the
- foreground is waiting on keyboard input.
-
- You may be required to issue INT 2A on entry, and exit
- immediately if returns with carry set. If carry is not set
- you must also call INT 2A before exiting your interrupt
- routine.
-
- Intercept ROM BIOS calls to reject any calls on the device
- being used by the background job.
-
- Do not attempt to execute while the foreground
- job has called the ROM BIOS disk (INT 13) functions.
-
- Do not attempt to execute if INDOS byte or the byte before it
- have any bits set.
-
- Do not attempt to execute if any other hardware interrupts
- are being processed.
-
- It is possible to do normal DOS file handling calls, but
- it may be necessary to perform additional actions similar to
- (undocmented) DOS functions 50 and 51. A call to DOS function
- 5D may also be necessary after all file stuff is finished.
-
-
- Enjoy!!